package controller;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;

import dal.JMLDatabase;
import dal.datastore.TableData;
import dto.ColumnDTO;
import dto.RowDTO;

public class TableController {
	private String dbname;

	private String name;
	private ArrayList<ColumnDTO> columns;
	private JMLDatabase dao;

	/**
	 * Constructor
	 * 
	 * @param dbname
	 * @param name
	 * @param columns
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public TableController(String dbname, String name,
			ArrayList<ColumnDTO> columns) throws UnknownHostException,
			IOException {
		super();
		this.dbname = dbname;
		this.name = name;
		this.columns = columns;
		this.dao = new JMLDatabase();
	}

	/**
	 * Constructor
	 * 
	 * @param name
	 * @param columns
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public TableController(String name, ArrayList<ColumnDTO> columns)
			throws UnknownHostException, IOException {
		super();
		this.name = name;
		this.columns = columns;
		this.dao = new JMLDatabase();
	}

	/**
	 * Constructor
	 * 
	 * @param tableName
	 *            the name of the table
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public TableController(String tableName) throws UnknownHostException,
			IOException {
		super();
		this.name = tableName;
		this.dao = new JMLDatabase();
	}

	/**
	 * Constructor
	 * 
	 * @param dbname
	 *            database name
	 * @param name
	 *            table name
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public TableController(String dbname, String name) throws UnknownHostException, IOException {
		super();
		this.dbname = dbname;
		this.name = name;
		this.dao = new JMLDatabase();
	}

	/**
	 * Get name
	 * 
	 * @return Table name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Set table name
	 * 
	 * @param name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Get columns
	 * 
	 * @return ArrayList<ColumnDTO>
	 */
	public ArrayList<ColumnDTO> getColumns() {
		return columns;
	}

	/**
	 * Set columns
	 * 
	 * @param columns
	 *            ArrayList<ColumnDTO>
	 */
	public void setColumns(ArrayList<ColumnDTO> columns) {
		this.columns = columns;
	}

	/**
	 * Create table inside a database.
	 * 
	 * @param dbname
	 * @return
	 * @throws Exception
	 */
	public boolean createTable() throws Exception {
		if (!isValidName(this.dbname) || !isValidName(this.name)) {
			throw new Exception("Table name or database name is invalid");
		}
		return dao.createTable(this.dbname, this.name, columns);
	}

	public ArrayList<ColumnDTO> getTableColumns() throws Exception {
		if (!isValidName(this.dbname) || !isValidName(this.name)) {
			throw new Exception("Table name or database name is invalid");
		}
		return dao.getTableColumns(this.dbname, this.name);
	}

	/**
	 * check database name is valid or not?
	 * 
	 * @return true if valid false if invalid.
	 */
	public boolean isValidName(String name) {
		if (name.isEmpty()) {
			return false;
		}
		// replace black char with _ char
		name = name.replace(' ', '_');
		return true;
	}

	/**
	 * get database name
	 * 
	 * @return
	 */
	public String getDbname() {
		return dbname;
	}

	/**
	 * set database name
	 * 
	 * @param dbname
	 *            database name
	 */
	public void setDbname(String dbname) {
		this.dbname = dbname;
	}

	/**
	 * Drop the table
	 * 
	 * @return
	 * @throws Exception
	 */
	public boolean dropTable() throws Exception {
		if (!isValidName(this.name)) {
			throw new Exception("Table name is invalid");
		}

		return dao.dropTable(this.dbname, this.name);
	}

	/**
	 * Insert rows to database data.
	 * 
	 * @param rows
	 *            ArrayList<RowDTO>
	 * @return true if succeed
	 * @throws Exception
	 * @author Stanley
	 */
	public boolean insertRows(ArrayList<RowDTO> rows) throws Exception {
		if (!isValidName(dbname)) {
			throw new Exception("Database name is invalid");
		}
		if (!isValidName(name)) {
			throw new Exception("Table name is invalid");
		}
		if (rows == null) {
			throw new Exception("Table data is null");
		}

		return dao.insertRows(this.dbname, this.name, rows);
	}

	public boolean edit200Rows(ArrayList<RowDTO> rows) throws Exception {
		if (!isValidName(dbname)) {
			throw new Exception("Database name is invalid");
		}
		if (!isValidName(name)) {
			throw new Exception("Table name is invalid");
		}
		if (rows == null) {
			throw new Exception("Table data is null");
		}
		return dao.replaceTableData(this.dbname, this.name, new TableData(
				this.name, rows));
	}

	/**
	 * Get 200 first rows of table data.
	 * 
	 * @return ArrayList<RowDTO>
	 * @throws Exception
	 * @author Stanley
	 */
	public ArrayList<RowDTO> select200FirstRow() throws Exception {
		if (!isValidName(dbname)) {
			throw new Exception("Database name is invalid");
		}
		if (!isValidName(name)) {
			throw new Exception("Table name is invalid");
		}
		return dao.select200Rows(this.dbname, this.name);
	}
}
